/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.grnt.buddy;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import org.grnt.common.ContextWraper;
import org.grnt.dbcommon.DataControler.DataControlException;
import org.grnt.dbcommon.DataControler;
import org.grnt.dbcommon.ResultBean;
import static org.grnt.buddy.BuddiesContext.*;

/**
 * This class implement init buddies tree actions. Buddies tree is described in
 * ServletContext object with many map objects. They are inited by this class object.
 * @author sayid
 */
public class BuddiesTreeInit {
	static Users users = null;
	static Buddies buddies = null;
	static UsersIndex usersIndex = null;
	static BuddiesIndex buddiesIndex = null;
	static UserLocks userLocks = null;

	static final ServletContext context = ContextWraper.getEntity();
	/**
	 *
	 * @throws org.grnt.buddy.BuddiesTreeInit.BuddiesInitException
	 * @throws org.grnt.dbcommon.DataControler.DataControlException
	 */
	public static void init() throws BuddiesInitException, DataControlException{
		if ((users = getUsers()) == null) {
			users = new Users();
			context.setAttribute("users", users);
		}
		if ((buddies = getBuddies()) == null) {
			buddies = new Buddies();
			context.setAttribute("buddies", buddies);
		}
		if ((usersIndex = getUsersIndex()) == null) {
			usersIndex = new UsersIndex();
			context.setAttribute("usersIndex", usersIndex);
		}
		if((buddiesIndex = getBuddiesIndex()) == null) {
			buddiesIndex = new BuddiesIndex();
			context.setAttribute("buddiesIndex", buddiesIndex);
		}
		if((userLocks = getUserLocks()) == null) {
			userLocks = new UserLocks();
			context.setAttribute("userLocks", userLocks);
		}
		users.clear();
		buddies.clear();
		usersIndex.clear();
		buddiesIndex.clear();
		userLocks.clear();

		retrieveObjects();
		createIndex();
	}

	final static class BuddiesResult implements ResultBean {

		final public String getQueryString() {
			return "SELECT * FROM gt_buddies_tree";
		}

		final public void fullValues(ResultSet rs) throws FullValuesException{
			try {
				rs.beforeFirst();
				while (rs.next()) {
					BuddyBean buddy = new BuddyBean();
					buddy.init(
							rs.getLong("buddy_id")
							, rs.getString("alias")
							, rs.getLong("parent")
							, rs.getLong("owner")
							, rs.getLong("user_id")
							, rs.getBoolean("is_group"));
					BuddyDecorator item = null;
					TreeSet<Long> subSet = null;
					if (buddy.getIsGroup()) {
						subSet = new TreeSet<Long>();
					}
					item = new BuddyDecorator(buddy, subSet);
					buddies.put(buddy.getBuddyId(), item);
				}
			} catch (SQLException ex) {
				Logger.getLogger(BuddiesTreeInit.class.getName()).log(Level.SEVERE, null, ex);
				throw new FullValuesException(ex);
			}
		}
	}


	final static class UsersResult implements ResultBean {
		final public String getQueryString() {
			return "SELECT * FROM gt_users";
		}

		final public void fullValues(ResultSet rs) throws FullValuesException{
			try {
				while (rs.next()) {
					UserBean user = new UserBean();
					user.init(rs.getLong("user_id"), rs.getString("login_name"), rs.getString("password"), rs.getLong("root"));
					TreeSet<Long> subSet = new TreeSet<Long>();
					TreeSet<Long> shadowsSet = new TreeSet<Long>();
					UserDecorator item = new UserDecorator(user, subSet, shadowsSet);
					users.put(user.getUserId(), item);
				}
			} catch (SQLException ex) {
				throw new FullValuesException(ex);
			}
		}
	}

	private final static void retrieveObjects() throws DataControlException, BuddiesInitException {
		UsersResult us = new UsersResult();
		DataControler.query(us);
		BuddiesResult bs = new BuddiesResult();
		DataControler.query(bs);
		for (BuddyDecorator item : buddies.values()) {
			BuddyBean itemBuddy = item.getBuddyBean();
			Long buddyId = itemBuddy.getBuddyId();
			Long parentId = itemBuddy.getParentId();

			if ((parentId != null) && (parentId != 0)) {
				TreeSet<Long> parentSet = buddies.get(parentId).getChildren();
				if (parentSet == null) {
					throw new DataControlException("Group buddy's contoner is null!");
				} else {
					parentSet.add(buddyId);
				}
			}

			Long ownerId = itemBuddy.getOwner();
			if ((ownerId == null) || (ownerId == 0)) {
				throw new BuddiesInitException(
						"The owner id in the buddy '"
						+ buddyId + "' is null or zero");
			}

			users.get(ownerId).getSubBuddies().add(buddyId);

			if (!itemBuddy.getIsGroup()) {
				Long userId = itemBuddy.getUserId();
				if ((userId == null) || (userId == 0)) {
					throw new BuddiesInitException(
							"The user id in the buddy '"
							+ buddyId + "' is null or zero");
				}
				users.get(userId).getShadows().add(buddyId);
			}
		}
	}

	private final static void createIndex(){
		for (UserDecorator item: users.values()) {
			UserBean user = item.getUserBean();
			Long userId = user.getUserId();
			String loginName = user.getLoginName();
			usersIndex.put(loginName, userId);
		}
		for (BuddyDecorator item: buddies.values()) {
			BuddyBean buddy = item.getBuddyBean();
			Long buddyId = buddy.getBuddyId();
			String absAlias = BuddiesTreeControler.absAlias(buddyId);
			buddiesIndex.put(absAlias, buddyId);
		}
	}

	/**
	 *
	 */
	public static class BuddiesInitException extends Exception {
		/**
		 *
		 * @param cause
		 */
		public BuddiesInitException(Throwable cause) {
			super(cause);
		}

		/**
		 *
		 * @param message
		 * @param cause
		 */
		public BuddiesInitException(String message, Throwable cause) {
			super(message, cause);
		}

		/**
		 *
		 * @param message
		 */
		public BuddiesInitException(String message) {
			super(message);
		}

		/**
		 *
		 */
		public BuddiesInitException() {
			super();
		}
	}
}
